'''
Created on 09/04/2010

@author: User
'''
import gdata.youtube.service

from Models import DTO
from Models import Playlist
from Models import Song, KnownUser
from Models import SongVSplaylist, Properties
from google.appengine.api import users
#from gdata.Crypto.Hash.HMAC import new


class SongUtils:
     
    def addSong(self, playlist_id, song_info):
        newsong = Song()
        newsong.name = song_info.name
        newsong.artist = song_info.artist
        newsong.title = song_info.title
        newsong.album = song_info.album
        newsong.time = song_info.time
        newsong.duration = song_info.duration
        newsong.genre = song_info.genre
        if (newsong.genre == ""):
            newsong.genreStatus = '0'
        else:
            newsong.genreStatus = '1'
        newsong.id = song_info.id 
        newsong.path = ""
        #newsong.isValid = True#newline
        if (newsong.name != ""):
            if (newsong.artist != ""):
                if (newsong.album != ""):
                    newsong.infoStatus = '3'
                else:
                    newsong.infoStatus = '2'
            else:
                newsong.infoStatus = '1'
        else:
            newsong.infoStatus = '0'               
        newsong.put()
        new_sVSp = SongVSplaylist()
        new_sVSp.playlist_id = playlist_id #in string
        new_sVSp.song_id = str(newsong.key()) #in string
        new_sVSp.put()        
        return str(newsong.key())
    
    def addSongExtension (self, videoId):
        userCheck = KnownUser.gql("WHERE kuser = :1", users.get_current_user()).count()
        if (userCheck == 0): 
            return False
        else:
            all = Playlist.gql("WHERE user = :1 AND name = :2", users.get_current_user(), 'All').get()
            newsong = Song()
            newsong.name = ""
            newsong.artist = ""
            newsong.title = "omar - check"
            newsong.album = ""
            newsong.time = "100"
            newsong.duration = 100
            newsong.genre = ""
            newsong.genreStatus = '0'
            newsong.id = videoId 
            newsong.path = ""
            newsong.infoStatus = '0'               
            newsong.put()
            new_sVSp = SongVSplaylist()
            new_sVSp.playlist_id = str(all.key()) #in string
            new_sVSp.song_id = str(newsong.key()) #in string
            new_sVSp.put()        
            return True            
            
    
    def addSongByPath(self, playlist_id, song_info):
        newsong = Song()
        newsong.name = song_info.name
        newsong.artist = song_info.artist
        newsong.title = song_info.title
        newsong.album = song_info.album
        newsong.time = song_info.time
        newsong.duration = song_info.duration
        newsong.genre = song_info.genre
        if (newsong.genre == ""):
            newsong.genreStatus = '0'
        else:
            newsong.genreStatus = '1'
        newsong.path = song_info.path
        if (newsong.name != ""):
            if (newsong.artist != ""):
                if (newsong.album != ""):
                    newsong.infoStatus = '3'
                else:
                    newsong.infoStatus = '2'
            else:
                newsong.infoStatus = '1'
        else:
            newsong.infoStatus = '0'        
        newsong.put()
        
        new_sVSp = SongVSplaylist()
        new_sVSp.playlist_id = playlist_id #in string
        new_sVSp.song_id = str(newsong.key()) #in string
        new_sVSp.put()        
        return str(newsong.key())
     
    def searchForYoutubeSong(self,keystring):    	
        song = Song.get(keystring)
        yt_service = gdata.youtube.service.YouTubeService()
        query = gdata.youtube.service.YouTubeVideoQuery()      
        
        if ((song.name != "") & (song.artist != "")):
            query.vq = song.artist + " " + song.name
            query.racy = 'exclude'
            query.format = '5'
            query.max_results = '1'
            feed = yt_service.YouTubeQuery(query) 
            song.id = ""           
            for entry in feed.entry:                
                song.id = entry.id.text[(entry.id.text.rfind("/") + 1):]
                #song.isValid = True#newline
            song.put()
        else:
            song.id = ""
            #song.isValid = False#newline
            song.put()            

        return song.id
       
    def addSongToPlaylist (self, playlist_id, song_id):
        new_sVSp = SongVSplaylist()
        new_sVSp.playlist_id = playlist_id #in string
        new_sVSp.song_id = song_id #in string
        new_sVSp.put()        
        return song_id
        
   
    def deleteSong(self,songKeystring,playlistKeystring):
        song = Song.get(songKeystring)
        playlist = Playlist.get(playlistKeystring)
        if (playlist.isDefault):
            sVSpArr = SongVSplaylist.gql("WHERE song_id = :1", songKeystring).fetch(1000)
            for sVSp in sVSpArr:
                sVSp.delete()            
            song.delete()
        else:
            sVSpArr = SongVSplaylist.gql("WHERE song_id = :1 AND playlist_id = :2", songKeystring, playlistKeystring).fetch(10)
            for sVSp in sVSpArr:
                sVSp.delete()
        return 1     
            
     
    def retrieveSong(self, song_id):
        song = Song.get(song_id)
        return self.to_dto(song,False)
    
    
    def retrievePlaylist(self, keystring, isDesktop): 
        yt_service = gdata.youtube.service.YouTubeService()#newline        
        song_keys = SongVSplaylist.gql("WHERE playlist_id = :1", keystring).fetch(1000)
        songs_dto =[]        
        if (isDesktop):
            for song_key in song_keys:
                song = Song.get(song_key.song_id)
                validation = True#newline
                entry = None#newline            
                try:#newline
                    entry = yt_service.GetYouTubeVideoEntry(video_id=song.id)#newline
                except:#newline
                    validation = False#newline
                                  
                if (song.path == ""):
                    if validation or entry:#newline
                        mark = 1#newline
                    else:#newline
                        mark = 0#newline
                else:
                    mark = 1                
                songs_dto.append(self.to_dto(song,mark))
        else:
            prop = Properties.gql("WHERE user = :1", users.get_current_user().email()).get()
            if prop.findAlternatives:            
                for song_key in song_keys:
                    song = Song.get(song_key.song_id)
                    
                    validation = True#newline
                    entry = None#newline            
                    try:#newline
                        entry = yt_service.GetYouTubeVideoEntry(video_id=song.id)#newline
                    except:#newline
                        validation = False#newline
                                      
                    if (song.id != ""):
                        if validation or entry:#newline
                            isValid = 1#newline
                        else:#newline
                            isValid = 0#newline
                        
                        if (song.path == ""):
                            isLocal = 0
                        else:
                            isLocal = 1 
                            
                        mark = 2*isLocal + isValid
                                                   
                        songs_dto.append(self.to_dto(song, mark))
            else:
                for song_key in song_keys:
                    song = Song.get(song_key.song_id)
                    if (song.path == ""):
                        validation = True#newline
                        entry = None#newline            
                        try:#newline
                            entry = yt_service.GetYouTubeVideoEntry(video_id=song.id)#newline
                        except:#newline
                            validation = False#newline
                                          
                        if (song.id != ""):
                            if validation or entry:#newline
                                mark = 1#newline
                            else:#newline
                                mark = 0#newline
                        songs_dto.append(self.to_dto(song,mark))                
        return songs_dto
     
    def editSongInfo(self, song_info):
        song = Song.get(song_info.keyString)
        song.name = song_info.name
        song.artist = song_info.artist
        song.title = song_info.title
        song.album = song_info.album
        song.time = song_info.time
        song.duration = song_info.duration
        song.genre = song_info.genre
        if (song.genre == ""):
            song.genreStatus = '0'
        else:
            song.genreStatus = '1'
        song.id = song_info.id  
        song.path = song_info.path
        if (song.name != ""):
            if (song.artist != ""):
                if (song.album != ""):
                    song.infoStatus = '3'
                else:
                    song.infoStatus = '2'
            else:
                song.infoStatus = '1'
        else:
            song.infoStatus = '0'                    
        song.put()
        return 1
      
    def addSongs(self, playlistKey, songsArray):
        for song_info in songsArray:
            self.addSong(playlistKey, song_info)
        return 1
    
    def updateSongVideoId (self, keyString, videoId):
        song = Song.get(keyString)
        song.id = videoId
        #song.isValid = True#newline
        song.put()
        return 1

    def fetchAvailableSongInfo(self, videoId):
        song = Song.gql("WHERE id = :1 AND infoStatus = :2", videoId, '3').get()
        if (song == None):
            song = Song.gql("WHERE id = :1 AND infoStatus = :2", videoId, '2').get()            
        if song:
            if (song.genre == ""):
                song2 = Song.gql("WHERE id = :1 AND genreStatus = :2", videoId, '1').get()
                if song2:
                    song.genre = song2.genre                              
            return self.to_dto(song,False)
        else:
            dto = DTO()
            dto.id = ""
            return dto

    def to_dto(self, song, mark):
        if song is None: return None
        dto = DTO()
        dto.keyString = str(song.key())
        dto.name = song.name
        dto.artist = song.artist
        dto.title = song.title
        dto.album = song.album
        dto.time = song.time
        dto.duration = song.duration
        dto.genre = song.genre
        dto.path = song.path
        dto.id = song.id  
        dto.mark = mark
        #dto.isValid = song.isValid#newline    
        return dto


    def addSongByPathMultiple(self, playlist_id, song_info_arr):
        returnArr = []
        for song_info in song_info_arr:
            newsong = Song()
            newsong.name = song_info.name
            newsong.artist = song_info.artist
            newsong.title = song_info.title
            newsong.album = song_info.album
            newsong.time = song_info.time
            newsong.duration = song_info.duration
            newsong.genre = song_info.genre
            if (newsong.genre == ""):
                newsong.genreStatus = '0'
            else:
                newsong.genreStatus = '1'
            newsong.path = song_info.path
            if (newsong.name != ""):
                if (newsong.artist != ""):
                    if (newsong.album != ""):
                        newsong.infoStatus = '3'
                    else:
                        newsong.infoStatus = '2'
                else:
                    newsong.infoStatus = '1'
            else:
                newsong.infoStatus = '0'        
            newsong.put()
            
            new_sVSp = SongVSplaylist()
            new_sVSp.playlist_id = playlist_id #in string
            new_sVSp.song_id = str(newsong.key()) #in string
            new_sVSp.put()
            returnArr.append(str(newsong.key()))
                    
        return returnArr
     
    def searchForYoutubeSongMultiple(self,keystrings_arr):        
        return_arr = []
        yt_service = gdata.youtube.service.YouTubeService()
        for keystring in keystrings_arr:
            song = Song.get(keystring)
            query = gdata.youtube.service.YouTubeVideoQuery()      
            
            if ((song.name != "") & (song.artist != "")):
                query.vq = song.artist + " " + song.name
                query.racy = 'exclude'
                query.format = '5'
                query.max_results = '1'
                feed = yt_service.YouTubeQuery(query) 
                song.id = ""           
                for entry in feed.entry:                
                    song.id = entry.id.text[(entry.id.text.rfind("/") + 1):]
                    #song.isValid = True#newline
                song.put()
            else:
                song.id = ""
                #song.isValid = False#newline
                song.put()
            return_arr.append(song.id)            

        return return_arr

    def addSongObjectByPath (self, playlist_id, song_info,requestId):
        newsong = Song()
        newsong.name = song_info.name
        newsong.artist = song_info.artist
        newsong.title = song_info.title
        newsong.album = song_info.album
        newsong.time = song_info.time
        newsong.duration = song_info.duration
        newsong.genre = song_info.genre
        if (newsong.genre == ""):
            newsong.genreStatus = '0'
        else:
            newsong.genreStatus = '1'
        newsong.path = song_info.path
        if (newsong.name != ""):
            if (newsong.artist != ""):
                if (newsong.album != ""):
                    newsong.infoStatus = '3'
                else:
                    newsong.infoStatus = '2'
            else:
                newsong.infoStatus = '1'
        else:
            newsong.infoStatus = '0'        
        newsong.put()
        
        new_sVSp = SongVSplaylist()
        new_sVSp.playlist_id = playlist_id #in string
        new_sVSp.song_id = str(newsong.key()) #in string
        new_sVSp.put()   
                
        dto = DTO()
        dto.name = newsong.name
        dto.artist = newsong.artist
        dto.title = newsong.title
        dto.album = newsong.album
        dto.time = newsong.time
        dto.duration = newsong.duration
        dto.genre = newsong.genre
        dto.id = newsong.id
        dto.plKey = playlist_id
        dto.songKey = str(newsong.key()) 
        dto.requestId = requestId 
           
        return dto

    def searchForYoutubeRequestedSong (self,keystring,requestId):    	
        song = Song.get(keystring)
        yt_service = gdata.youtube.service.YouTubeService()
        query = gdata.youtube.service.YouTubeVideoQuery()      
        
        if ((song.name != "") & (song.artist != "")):
            query.vq = song.artist + " " + song.name
            query.racy = 'exclude'
            query.format = '5'
            query.max_results = '1'
            feed = yt_service.YouTubeQuery(query) 
            song.id = ""           
            for entry in feed.entry:                
                song.id = entry.id.text[(entry.id.text.rfind("/") + 1):]
                #song.isValid = True#newline
            song.put()
        else:
            song.id = ""
            #song.isValid = False#newline
            song.put() 
            
        dto = DTO()
        dto.videoId = song.id
        dto.requestId = requestId          

        return dto

    def changeSongPosition(self, playlistKey, songKey, old, new):
        songToUpdate = SongVSplaylist.gql("WHERE song_id = :1 AND playlist_id = :2 AND position = :3", songKey, playlistKey, old).get()
        songToUpdate.position = new
        
        if (old > new):            
            for i in range(old-1, new-1,-1):
                tmp = SongVSplaylist.gql("WHERE song_id = :1 AND playlist_id = :2 AND position = :3", songKey, playlistKey, i).get()
                tmp.position = tmp.position + 1
                tmp.put()            
        else:
            for i in range(old + 1, new + 1):
                tmp = SongVSplaylist.gql("WHERE song_id = :1 AND playlist_id = :2 AND position = :3", songKey, playlistKey, i).get()
                tmp.position = tmp.position - 1
                tmp.put()
        
        songToUpdate.put()
        return 1
    



########### duplicates ##########
    
    def addSongDup(self, playlist_id, song_info):
        newsong = Song()
        newsong.name = song_info.name
        newsong.artist = song_info.artist
        newsong.title = song_info.title
        newsong.album = song_info.album
        newsong.time = song_info.time
        newsong.duration = song_info.duration
        newsong.genre = song_info.genre
        if (newsong.genre == ""):
            newsong.genreStatus = '0'
        else:
            newsong.genreStatus = '1'
        newsong.id = song_info.id 
        newsong.path = ""
        if (newsong.name != ""):
            if (newsong.artist != ""):
                if (newsong.album != ""):
                    newsong.infoStatus = '3'
                else:
                    newsong.infoStatus = '2'
            else:
                newsong.infoStatus = '1'
        else:
            newsong.infoStatus = '0'               
        newsong.put()
        new_sVSp = SongVSplaylist()
        new_sVSp.playlist_id = playlist_id #in string
        new_sVSp.song_id = str(newsong.key()) #in string
        new_sVSp.position = 1 + SongVSplaylist.gql("WHERE playlist_id = :1", playlist_id).count()
        new_sVSp.put()        
        return str(newsong.key())            
            
    def addSongByPathDup(self, playlist_id, song_info):
        newsong = Song()
        newsong.name = song_info.name
        newsong.artist = song_info.artist
        newsong.title = song_info.title
        newsong.album = song_info.album
        newsong.time = song_info.time
        newsong.duration = song_info.duration
        newsong.genre = song_info.genre
        if (newsong.genre == ""):
            newsong.genreStatus = '0'
        else:
            newsong.genreStatus = '1'
        newsong.path = song_info.path
        if (newsong.name != ""):
            if (newsong.artist != ""):
                if (newsong.album != ""):
                    newsong.infoStatus = '3'
                else:
                    newsong.infoStatus = '2'
            else:
                newsong.infoStatus = '1'
        else:
            newsong.infoStatus = '0'        
        newsong.put()
        
        new_sVSp = SongVSplaylist()
        new_sVSp.playlist_id = playlist_id #in string
        new_sVSp.song_id = str(newsong.key()) #in string
        new_sVSp.position = 1 + SongVSplaylist.gql("WHERE playlist_id = :1", playlist_id).count()
        new_sVSp.put()        
        return str(newsong.key())            
                
    def addSongToPlaylistDup (self, playlist_id, song_id):
        new_sVSp = SongVSplaylist()
        new_sVSp.playlist_id = playlist_id #in string
        new_sVSp.song_id = song_id #in string
        new_sVSp.position = 1 + SongVSplaylist.gql("WHERE playlist_id = :1", playlist_id).count()
        new_sVSp.put()        
        return song_id
        
   
    def deleteSongDup(self,songKeystring,playlistKeystring):
        song = Song.get(songKeystring)
        playlist = Playlist.get(playlistKeystring)
        if (playlist.isDefault):
            sVSpArr = SongVSplaylist.gql("WHERE song_id = :1", songKeystring).fetch(1000)
            for sVSp in sVSpArr:
                total = SongVSplaylist.gql("WHERE playlist_id = :1", playlistKeystring).count()
                deletedPosition = sVSp.position
                playlist = sVSp.playlist_id
                sVSp.delete()
                for i in range(deletedPosition + 1, total + 1):
                    tmp = SongVSplaylist.gql("WHERE song_id = :1 AND playlist_id = :2 AND position = :3", songKeystring, playlist, i).get()
                    tmp.position = tmp.position - 1
                    tmp.put()
            song.delete()
        else:
            sVSpArr = SongVSplaylist.gql("WHERE song_id = :1 AND playlist_id = :2", songKeystring, playlistKeystring).fetch(10)
            for sVSp in sVSpArr:
                total = SongVSplaylist.gql("WHERE playlist_id = :1", playlistKeystring).count()
                deletedPosition = sVSp.position
                sVSp.delete()
                for i in range(deletedPosition + 1, total + 1):
                    tmp = SongVSplaylist.gql("WHERE song_id = :1 AND playlist_id = :2 AND position = :3", songKeystring, playlistKeystring, i).get()
                    tmp.position = tmp.position - 1
                    tmp.put()                
        return 1                     

            
    def addSongByPathMultipleDup(self, playlist_id, song_info_arr):
        returnArr = []
        for song_info in song_info_arr:
            newsong = Song()
            newsong.name = song_info.name
            newsong.artist = song_info.artist
            newsong.title = song_info.title
            newsong.album = song_info.album
            newsong.time = song_info.time
            newsong.duration = song_info.duration
            newsong.genre = song_info.genre
            if (newsong.genre == ""):
                newsong.genreStatus = '0'
            else:
                newsong.genreStatus = '1'
            newsong.path = song_info.path
            if (newsong.name != ""):
                if (newsong.artist != ""):
                    if (newsong.album != ""):
                        newsong.infoStatus = '3'
                    else:
                        newsong.infoStatus = '2'
                else:
                    newsong.infoStatus = '1'
            else:
                newsong.infoStatus = '0'        
            newsong.put()
            
            new_sVSp = SongVSplaylist()
            new_sVSp.playlist_id = playlist_id #in string
            new_sVSp.song_id = str(newsong.key()) #in string
            new_sVSp.position = 1 + SongVSplaylist.gql("WHERE playlist_id = :1", playlist_id).count()
            new_sVSp.put()
            returnArr.append(str(newsong.key()))
                    
        return returnArr            
        
    def addSongObjectByPathDup (self, playlist_id, song_info,requestId):
        newsong = Song()
        newsong.name = song_info.name
        newsong.artist = song_info.artist
        newsong.title = song_info.title
        newsong.album = song_info.album
        newsong.time = song_info.time
        newsong.duration = song_info.duration
        newsong.genre = song_info.genre
        if (newsong.genre == ""):
            newsong.genreStatus = '0'
        else:
            newsong.genreStatus = '1'
        newsong.path = song_info.path
        if (newsong.name != ""):
            if (newsong.artist != ""):
                if (newsong.album != ""):
                    newsong.infoStatus = '3'
                else:
                    newsong.infoStatus = '2'
            else:
                newsong.infoStatus = '1'
        else:
            newsong.infoStatus = '0'        
        newsong.put()
        
        new_sVSp = SongVSplaylist()
        new_sVSp.playlist_id = playlist_id #in string
        new_sVSp.song_id = str(newsong.key()) #in string
        new_sVSp.position = 1 + SongVSplaylist.gql("WHERE playlist_id = :1", playlist_id).count()
        new_sVSp.put()   
                
        dto = DTO()
        dto.name = newsong.name
        dto.artist = newsong.artist
        dto.title = newsong.title
        dto.album = newsong.album
        dto.time = newsong.time
        dto.duration = newsong.duration
        dto.genre = newsong.genre
        dto.id = newsong.id
        dto.plKey = playlist_id
        dto.songKey = str(newsong.key()) 
        dto.requestId = requestId 
           
        return dto
    
    def retrievePlaylistDup(self, keystring, isDesktop):       
        song_keys = SongVSplaylist.gql("WHERE playlist_id = :1", keystring).fetch(1000)
        songs_dto =[]        
        if (isDesktop):
            for song_key in song_keys:
                song = Song.get(song_key.song_id)
                songs_dto.append(self.to_dto(song,False))
        else:
            prop = Properties.gql("WHERE user = :1", users.get_current_user().email()).get()
            if prop.findAlternatives:            
                for song_key in song_keys:
                    #position = song_key.position
                    song = Song.get(song_key.song_id)
                    if (song.id != ""):
                        if (song.path == ""):
                            isLocal = False
                        else:
                            isLocal = True                            
                        songs_dto.append(self.to_dto(song, isLocal))
            else:
                for song_key in song_keys:
                    song = Song.get(song_key.song_id)
                    if (song.path == ""):
                        songs_dto.append(self.to_dto(song,False))                
        return songs_dto
